<?php
/**
 +------------------------------------------------------------------------------
 *  解析xheditor生成的ubb标签
 *
 +------------------------------------------------------------------------------
 * @category   ORG
 * @package  ORG
 * @subpackage  Net
 * @author    wybwsk <wybwsk@qq.com>
 * @version   1.0
 +------------------------------------------------------------------------------
 */


class Ubb {
    /**
     * UbbHtml字符串
     *
     * @var string
     */
    private $sHtml = '';

    /**
     * 代码高亮记数
     *
     * @var int
     */
    private $cnum = 0;

    /**
     * 多段代码高亮
     *
     * @var array()
     */
    private $arrcode = array();

    /**
     * Ubb转Html开关
     *
     * @var boolean
     */
    private $bUbb2htmlFunctionInit = false;

    /**
     * 自定义表情路径
     *
     * @var string
     */
    public $emotPath = 'emot/';//表情根路径

    /**
     * swf播放器地址
     *
     * @var string
     */
    public $flashPlayPath = 'player.swf';

    /**
     * 设置ubb初始字符串
     *
     * @access private
     */
    public function __construct($sHtml){
        $this->sHtml = $sHtml;
    }

    /**
     * 回调方法,替换字体大小标签
     *
     * @access private
     * @return string
     */
    private function getSizeName($match){
        $arrSize = array('8pt','10pt','12pt','14pt','18pt','24pt','36pt');
        return '<span style="font-size:'.$arrSize[$match[1]-1].';">';
    }

    /**
     * 回调方法,替换图片标签
     *
     * @access private
     * @return string
     */
    private function getImg($match){
        $alt=$match[1];
        $p1=$match[2];
        $p2=$match[3];
        $p3=$match[4];
        $src=$match[5];
        $a = ($p3) ? $p3 : (!is_numeric($p1) ? $p1 : '' );
        return '<img src="'.$src.'" alt="'.$alt.'"'.(is_numeric($p1) ? ' width="'.$p1.'"' : '').(is_numeric($p2) ? ' height="'.$p2.'"' : '').($a?' align="'.$a.'"' : '').' />';
    }
    /**
     * 回调方法,替换自定义表情标签
     *
     * @access private
     * @return string
     */
    private function getEmot($match){
        $arr = explode(',',$match[1]);
        if(!isset($arr[1])){
            $arr[1] = $arr[0];
            $arr[0] = 'default';
        }
        $path = $this->emotPath.$arr[0].'/'.$arr[1].'.gif';
        return '<img src="'.$path.'" alt="'.$arr[1].'" />';
    }

    /**
     * 回调方法,替换flash标签
     *
     * @access private
     * @return string
     */
    private function getFlash($match){
        $w=$match[1];
        $h=$match[2];
        $url=$match[3];
        if(!$w)$w=480;
        if(!$h)$h=400;
        return '<embed type="application/x-shockwave-flash" src="'.$url.'" wmode="opaque" quality="high" bgcolor="#ffffff" menu="false" play="true" loop="true" width="'.$w.'" height="'.$h.'" />';
    }

    /**
     * 回调方法,替换media标签
     *
     * @access private
     * @return string
     */
    private function getMedia($match){
        $w=$match[1];
        $h=$match[2];
        $play=$match[3];
        $url=$match[4];
        if(!$w)$w=480;
        if(!$h)$h=400;
        return '<embed type="application/x-mplayer2" src="'.$url.'" enablecontextmenu="false" autostart="'.($play=='1'?'true':'false').'" width="'.$w.'" height="'.$h.'" />';
    }

    /**
     * 回调方法,替换table标签
     *
     * @access private
     * @return string
     */
    private function getTable($match){
        return '<table'.(isset($match[1]) ? ' width="'.$match[1].'"' : '').(isset($match[2]) ? ' bgcolor="'.$match[2].'"' : '').'>';
    }

    /**
     * 回调方法,替换tr标签
     *
     * @access private
     * @return string
     */
    private function getTR($match){
        return '<tr'.(isset($match[1]) ? ' bgcolor="'.$match[1].'"' : '').'>';
    }

    /**
     * 回调方法,替换td标签
     *
     * @access private
     * @return string
     */
    private function getTD($match){
        $col = isset($match[1]) ? $match[1] : 0;
        $row = isset($match[2]) ? $match[2] : 0;
        $w = isset($match[3]) ? $match[3] : null;
        return '<td'.($col>1?' colspan="'.$col.'"':'').($row>1?' rowspan="'.$row.'"':'').($w?' width="'.$w.'"':'').'>';
    }

    /**
     * 回调方法,替换列表标签
     *
     * @access private
     * @return string
     */
    private function getUL($match){
        $str='<ul';
        if(isset($match[1])) $str.=' type="'.$match[1].'"';
        return $str.'>';
    }

    /**
     * 回调方法,替换空格标签
     *
     * @access private
     * @return string
     */
    private function fixText($match){
        $text=$match[2];
        $text=preg_replace("/\t/",'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',$text);
        $text=preg_replace("/ /",'&nbsp;',$text);
        return $match[1].$text;
    }

    /**
     * 回调方法,初始化代码高亮
     *
     * @access private
     * @return string
     */
    private function saveCodeArea($match){
        $this->cnum++;
        $this->arrcode[$this->cnum] = $match[0];
        return "[\tubbcodeplace_".$this->cnum."\t]";
    }

    /**
     * 替换代码高亮标签
     * 需要加入prettify.css prettify.js文件和在页面最后使用<script type="text/javascript">prettyPrint();</script>才可生效
     * @access private
     * @return string
     */
    private function showCode($match){
        $match[1] = strtolower($match[1]);
        if(!$match[1]) $match[1]='plain';
        $match[2] = preg_replace("/</",'&lt;',$match[2]);
        $match[2] = preg_replace("/>/",'&gt;',$match[2]);
        return '<pre class="prettyprint lang-'.$match[1].'">'.$match[2].'</pre>';
    }

    /**
     * 替换flv标签
     *
     * @access private
     * @return string
     */
    private function showFlv($match){
	$w = $match[1];
        $h = $match[2];
        $url = $match[3];
	if(!$w) $w=480;
        if(!$h) $h=400;
	return '<embed type="application/x-shockwave-flash" src="'.$this->flashPlayPath.'" wmode="transparent" allowscriptaccess="always" allowfullscreen="true" quality="high" bgcolor="#ffffff" width="'.$w.'" height="'.$h.'" flashvars="file='.$url.'" />';
    }

     /**
     * 返回UbbHtml代码
     *
     * @access private
     * @return string
     */
    public function showUbb(){
        if ($this->bUbb2htmlFunctionInit === false){
            //初始化代码高亮标签
            $this->sHtml = preg_replace_callback('/\[code\s*(?:=\s*((?:(?!")[\s\S])+?)(?:"[\s\S]*?)?)?\]([\s\S]*?)\[\/code\]/i',array(&$this,'saveCodeArea'),$this->sHtml);
            $this->sHtml = preg_replace("/&/",'&amp;',$this->sHtml);
            $this->sHtml = preg_replace("/</",'&lt;',$this->sHtml);
            $this->sHtml = preg_replace("/>/",'&gt;',$this->sHtml);
            $this->sHtml = preg_replace("/\r?\n/",'<br />',$this->sHtml);
            $this->sHtml = preg_replace("/\[(\/?)(b|u|i|s|sup|sub)\]/i",'<$1$2>',$this->sHtml);
            $this->sHtml = preg_replace('/\[color\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]/i','<span style="color:$1;">',$this->sHtml);
            //替换字体大小标签
            $this->sHtml = preg_replace_callback("/\[size\s*=\s*(\d+?)\s*\]/i",array(&$this,'getSizeName'),$this->sHtml);
            $this->sHtml = preg_replace('/\[font\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]/i','<span style="font-family:$1;">',$this->sHtml);
            $this->sHtml = preg_replace('/\[back\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]/i','<span style="background-color:$1;">',$this->sHtml);
            $this->sHtml = preg_replace("/\[\/(color|size|font|back)\]/i",'</span>',$this->sHtml);
            for($i=0;$i<3;$i++){
                $this->sHtml = preg_replace('/\[align\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\](((?!\[align(?:\s+[^\]]+)?\])[\s\S])*?)\[\/align\]/','<p align="$1">$2</p>',$this->sHtml);
            }
            $this->sHtml = preg_replace('/\[img\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*?)?\s*\[\/img\]/i','<img src="$1" alt="" />',$this->sHtml);
            //替换图片标签
            $this->sHtml = preg_replace_callback('/\[img\s*=([^,\]]*)(?:\s*,\s*(\d*%?)\s*,\s*(\d*%?)\s*)?(?:,?\s*(\w+))?\s*\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*)?\s*\[\/img\]/i',array(&$this,'getImg'),$this->sHtml);
            //替换自定义表情标签
            $this->sHtml = preg_replace_callback('/\[emot\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\/\]/i',array(&$this,'getEmot'),$this->sHtml);
            $this->sHtml = preg_replace('/\[url\]\s*(((?!")[\s\S])*?)(?:"[\s\S]*?)?\s*\[\/url\]/i','<a href="$1">$1</a>',$this->sHtml);
            $this->sHtml = preg_replace('/\[url\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]\s*([\s\S]*?)\s*\[\/url\]/i','<a href="$1">$2</a>',$this->sHtml);
            $this->sHtml = preg_replace('/\[email\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*?)?\s*\[\/email\]/i','<a href="mailto:$1">$1</a>',$this->sHtml);
            $this->sHtml = preg_replace('/\[email\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]\s*([\s\S]+?)\s*\[\/email\]/i','<a href="mailto:$1">$2</a>',$this->sHtml);
            $this->sHtml = preg_replace("/\[quote\]([\s\S]*?)\[\/quote\]/i",'<blockquote>$1</blockquote>',$this->sHtml);
            //替换flash标签
            $this->sHtml = preg_replace_callback('/\[flash\s*(?:=\s*(\d+)\s*,\s*(\d+)\s*)?\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*?)?\s*\[\/flash\]/i',array(&$this,'getFlash'),$this->sHtml);
            //替换flv标签
            $this->sHtml=preg_replace_callback('/\[flv\s*(?:=\s*(\d+)\s*,\s*(\d+)\s*)?\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*?)?\s*\[\/flv\]/i',array(&$this,'showFlv'),$this->sHtml);
            //替换Midia标签
            $this->sHtml = preg_replace_callback('/\[media\s*(?:=\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d+)\s*)?)?\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*?)?\s*\[\/media\]/i',array(&$this,'getMedia'),$this->sHtml);
            //替换table标签
            $this->sHtml = preg_replace_callback('/\[table\s*(?:=(\d{1,4}%?)\s*(?:,\s*([^\]"]+)(?:"[^\]]*?)?)?)?\s*\]/i',array(&$this,'getTable'),$this->sHtml);
            //替换tr标签
            $this->sHtml = preg_replace_callback('/\[tr\s*(?:=(\s*[^\]"]+))?(?:"[^\]]*?)?\s*\]/i',array(&$this,'getTR'),$this->sHtml);
            //替换td标签
            $this->sHtml=preg_replace_callback("/\[td\s*(?:=\s*(\d{1,2})\s*,\s*(\d{1,2})\s*(?:,\s*(\d{1,4}%?))?)?\s*\]/i",array(&$this,'getTD'),$this->sHtml);
            $this->sHtml=preg_replace("/\[\/(table|tr|td)\]/i",'</$1>',$this->sHtml);
            $this->sHtml=preg_replace("/\[\*\]((?:(?!\[\*\]|\[\/list\]|\[list\s*(?:=[^\]]+)?\])[\s\S])+)/i",'<li>$1</li>',$this->sHtml);
            //替换列表标签
            $this->sHtml=preg_replace_callback('/\[list\s*(?:=\s*([^\]"]+))?(?:"[^\]]*?)?\s*\]/i',array(&$this,'getUL'),$this->sHtml);
            $this->sHtml=preg_replace("/\[\/list\]/i",'</ul>',$this->sHtml);
            for($i=1;$i<=$this->cnum;$i++){
                $this->sHtml=str_replace("[\tubbcodeplace_".$i."\t]", $this->arrcode[$i],$this->sHtml);
            }
            //替换换行符为8个空格
            $this->sHtml=preg_replace_callback('/(^|<\/?\w+(?:\s+[^>]*?)?>)([^<$]+)/i',array(&$this,'fixText'),$this->sHtml);
            //替换代码高亮
            $this->sHtml=preg_replace_callback('/\[code\s*(?:=\s*((?:(?!")[\s\S])+?)(?:"[\s\S]*?)?)?\]([\s\S]*?)\[\/code\]/i',array(&$this,'showCode'),$this->sHtml);
        }
        $this->bUbb2htmlFunctionInit = true;
        return $this->sHtml;
    }
}